home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / main.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  19KB  |  771 lines

  1. /*
  2.  * $Id: main.c,v 0.91 1994/02/20 00:52:46 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  *  Main program for BIT:
  26.  *    Version identification.
  27.  *    Parse the command line and walks down or up the file list.
  28.  *    Wait for Q-events and dispatch handling routines.
  29.  */
  30. #ifndef lint
  31. char *id_main = "$Id: main.c,v 0.91 1994/02/20 00:52:46 zhao Pre-Release $";
  32. #endif
  33.  
  34. #include "bit.h"
  35. #include <stdlib.h>
  36. #include "global.h"
  37. #include "extern.h"
  38. #include "forms.h"
  39.  
  40. /*****************************************************************
  41.  * current (short) revision identification shown in info panel
  42.  ******************************************************************/
  43.  
  44. const char *sver = "BIT ($State: Pre-Release $ $Revision: 0.91 $)";
  45.  
  46. /******************************************************************
  47.  * current (long) version name using -v. Also used by version_cb in
  48.  * control.c
  49.  ******************************************************************/
  50.  
  51. const char *p_version[] =
  52. {
  53.     "bit(Bitmap Image Touchup)"
  54.     "$State: Pre-Release $ $Revision: 0.91 $of$Date: 1994/02/20 00:52:46 $",
  55.     "Copyright (c) 1993, 1994 by T.C. Zhao", 0
  56. };
  57.  
  58.  
  59. static const char *fname;    /* current image filename */
  60.  
  61. /********** local functions (forward) *****/
  62.  
  63. static void remove_from_list(const char *);
  64. static void special_case(void);
  65. static const char *parse_command_line(int, char *[]);
  66. static int process_Q(void);
  67.  
  68. /********************************************************************
  69.  * Main entry point
  70.  ********************************************************************/
  71. int
  72. main(int argc, char *argv[])
  73. {
  74.     IPTR im;
  75.  
  76.     /* set all options and grab the first filename */
  77.     fname = parse_command_line(argc, argv);
  78.  
  79.     /* show help/welcome screen only if there is no arg */
  80.     if (argc < 2)
  81.     version_cb(0, 0);
  82.  
  83.     /*
  84.      * Main loop. Call appropriate functions to handle loading, displaying,
  85.      * window manager Q events. Quit when ESC is pressed
  86.      */
  87.  
  88.     do
  89.       {
  90.       if (fname)
  91.         {
  92.         /*
  93.          * although all text and sgfs are relative to image, there
  94.          * might be cases where we want to have them carried over to
  95.          * the next image. Must not do this after image is loaded
  96.          * because the new image might have its own texts and we
  97.          * certainly do not want delete them before displaying.
  98.          */
  99.  
  100.         if (!keepmisc)
  101.           {
  102.               del_text();
  103.               del_marking();
  104.           }
  105.  
  106. #ifdef TIGHT_MEM
  107.  
  108.         /* if last image is large, free  memory */
  109.         if (imgptr && (imgptr->size > MAXMEMK))
  110.           {
  111.               free_image_mem(imgptr);
  112.           }
  113. #endif
  114.  
  115.         if ((im = load_image(fname)))
  116.           {        /* success */
  117.               free_image(imgptr);
  118.  
  119.               /*
  120.                * This is very important as imgptr is a global
  121.                * variable and used in various window manager's event
  122.                */
  123.  
  124.               imgptr = im;
  125.  
  126.               /* display with requested style */
  127.               im->io->display(im, display_style, always_clear);
  128.  
  129.               /* if in slidemode, pan */
  130.               auto_pan(imgptr);
  131.  
  132.               /*
  133.                * check if more than one image present and if yes,
  134.                * call the multiple image handler
  135.                */
  136.               if (imgptr->more && imgptr->io->inext)
  137.               handle_multi_images(imgptr);
  138.           }
  139.         else
  140.           {
  141.               /*
  142.                * unable to load the darn thing, remove it from the
  143.                * active file list
  144.                */
  145.               remove_from_list(fname);
  146.  
  147.               /*
  148.                * Need special handling if main window is not opened.
  149.                * This could happen if fit_image_size is requested
  150.                */
  151.               special_case();
  152.           }
  153.         }
  154.       }
  155.     while (!process_Q());
  156.  
  157.     clean_up();
  158.  
  159.     return 0;
  160. }
  161.  
  162. /***************************************************************
  163.  * print out all supported formats by calling enumerate_formats,
  164.  * which generates a string for each format. print_format will
  165.  * just print it out. first is a hack to get 2 formats per line
  166.  *****************************************************************/
  167.  
  168. static int showfmts;
  169. static void
  170. print_format(const char *str)
  171. {
  172.     static int first = 1;
  173.     fprintf(stderr, (first = !first) ? "%s\n" : "  %s\t\t", str);
  174. }
  175.  
  176. /*************************************************************
  177.  * Print current version number and optionally exit
  178.  *************************************************************/
  179.  
  180. static void
  181. print_version(int die)
  182. {
  183.     const char **p = p_version;
  184.  
  185.     do
  186.       {
  187.       fprintf(stderr, "%s\n", rm_rcs_kw(*p));
  188.       }
  189.     while (*++p);
  190.  
  191.  
  192.     if (showfmts)
  193.       {
  194.       fputs("\nBit recognizes the following formats "
  195.         "[+:WriteOnly -:ReadOnly]\n", stderr);
  196.       enumerate_formats(print_format);
  197.       putc('\n', stderr);
  198.       }
  199.  
  200.  
  201.     if (die)
  202.     clean_up();
  203. }
  204.  
  205. /*******************************************************************
  206.  * Command line options and messages
  207.  *******************************************************************/
  208.  
  209. static const char *optstr = "hfviIqenabrCRFNc:s:x:y:p:m:d:PS";
  210. static const char *opt = "[-hfvIqenabrCRFN][-x|y f][-m l][-d styl][-s sec]"
  211. "[-c f][-p d]";
  212.  
  213. /*
  214.  * usually only opt is printed, helps will be printed if -h
  215.  * is present on command line
  216.  */
  217. static const char *helps[] =
  218. {
  219.     "a: enable Automatic initial window placement",
  220.     "b: prevent bit from running in Background",
  221.     "c: use alternate Configuration file",
  222.     "C: show Clock_mailbox window upon startup",
  223.     "d: display style [0-16]. Use 100 for cyclic styles",
  224.     "e: show Editing panel",
  225.     "f: show all supported Formats",
  226.     "F: run bit in full screen",
  227.     "h: for this Help",
  228.     "I: forcing initial window size to be that of the 1st Image",
  229.     "m: set to Message output level (0-4), default is 1",
  230.     "n: do Not read configuration file",
  231.     "N: No initial panels",
  232.     "p: default Path",
  233.     "q: Quiet mode. Only error message will be printed, same as -m0",
  234.     "r: not to Refresh screen before display",
  235.     "R: suppress progress report",
  236.     "s: pause interval between Slides (in seconds)",
  237.     "v: print Version number",
  238.     "x: magnification factor in X-direction. 0 for automatic",
  239.     "y: magnification factor in Y-direction. 0 for automatic",
  240.     0
  241. };
  242.  
  243. /****************************************************************
  244.  * Help messages
  245.  ****************************************************************/
  246. extern int getopt(int, char *const *, const char *);
  247. static void
  248. usage(const char *cmd, int v)
  249. {
  250.     const char **p = helps;
  251.  
  252.     print_version(0);
  253.     fprintf(stderr, "Usage: %s %s files\n", cmd, opt);
  254.     if (v)
  255.       {                /* detailed help */
  256.       do
  257.         {
  258.         fprintf(stderr, "\t%s\n", *p);
  259.         }
  260.       while (*++p);
  261.       }
  262.     clean_up();
  263. }
  264.  
  265. /***********************************************************************
  266.  * Do the command line options. Note that we have to preserve all copies
  267.  * of the options before init_configure as we want to have the command line
  268.  * options to overwrite whatever is set in the configuration file.  Nasty!
  269.  *************************************************************************/
  270.  
  271. /* default bit dir. personalized configurations reside there*/
  272.  
  273. char bitpath[MAXDLEN];        /* bit help/icon files path    */
  274. char helppath[MAXDLEN];        /* directory bit launched from */
  275. char startdir[MAXDLEN];        /* start up directory          */
  276. char tmppath[MAXDLEN];        /* scratch directory           */
  277. static char homedir[MAXDLEN];    /* home  directory             */
  278.  
  279. /******************************************************************
  280.  * Parse all command line options and overide whatever read
  281.  * from the startup file(s). Return the first non-option
  282.  * argument
  283.  ******************************************************************/
  284.  
  285. int force_pupdraw;        /* undocumented */
  286.  
  287. static const char *
  288. parse_command_line(int argc, char *argv[])
  289. {
  290.     int c, noconfig = 0;
  291.     const char *firstfile = 0;
  292.     extern char *optarg;
  293.     char configfile[100];
  294.     extern int opterr, optind;
  295.     /* copies */
  296.     int s_always_clear, s_report;
  297.     int s_verbose, s_showedit, s_pause_index;
  298.     int s_style;
  299.     float s_g_zoomx, s_g_zoomy;
  300.  
  301.     fix_dir_tail(getcwd(startdir, MAXDLEN - 2));
  302.  
  303.     opterr = 0;
  304.     strcpy(configfile, "Setup.opt");
  305.  
  306.     while ((c = getopt(argc, argv, optstr)) != EOF)
  307.       {
  308.       switch (c)
  309.         {
  310.         case 'S':        /* undocumented */
  311.         form_single = 1;
  312.         break;
  313.         case 'P':        /* undocumented */
  314.         force_pupdraw = 1;
  315.         break;
  316.         case 'R':
  317.         s_report = report_level = 0;
  318.         break;
  319.         case 'a':
  320.         auto_position = 1;
  321.         break;
  322.         case 'b':
  323.         run_in_background = 0;
  324.         break;
  325.         case 's':
  326.         /* allow minimum 0.02 second */
  327.         if ((slideshow = (1000.0 * atof(optarg))) < 20)
  328.             slideshow = 20;
  329.         break;
  330.         case 'h':
  331.         usage(argv[0], 1);
  332.         break;
  333.         case 'f':
  334.         case 'v':
  335.         showfmts = (c == 'f');
  336.         print_version(1);
  337.         break;
  338.         case 'n':
  339.         noconfig = 1;
  340.         break;
  341.         case 'c':
  342.         Strncpy(configfile, optarg, sizeof(configfile) - 1);
  343.         break;
  344.         case 'C':
  345.         no_clockmail = 0;
  346.         break;
  347.         case 'p':
  348.         strcpy(bitpath, optarg);
  349.         break;
  350.         case 'r':
  351.         always_clear = 0;
  352.         break;
  353.         case 'i':
  354.         fit_image_size = 1;
  355.         break;
  356.         case 'I':
  357.         fit_image_size = 2;
  358.         break;
  359.         case 'e':
  360.         showedit = !showedit;
  361.         break;
  362.         case 'm':
  363.         verbose = atoi(optarg);
  364.         set_msg_threshold(verbose);
  365.         break;
  366.         case 'd':
  367.         display_style = atoi(optarg);
  368.         break;
  369.         case 'q':
  370.         verbose = 0;
  371.         break;
  372.         case 'x':
  373.         /* only supports integer zoom factors */
  374.         g_zoomx = atoi(optarg);
  375.         break;
  376.         case 'y':
  377.         /* only supports integer zoom factors */
  378.         g_zoomy = atoi(optarg);
  379.         break;
  380.         case 'F':
  381.         full_win = 1;
  382.         break;
  383.         case 'N':
  384.         no_panel = 1;
  385.         break;
  386.         default:
  387.         usage(argv[0], 0);
  388.         break;
  389.         }
  390.       }
  391.  
  392.     if (g_zoomx <= 0.5 || g_zoomy < 0.5)
  393.     g_zoomx = g_zoomy = 0.0;
  394.  
  395.     /*
  396.      * initialize non-graphics variables, check graphics capabilities,
  397.      * initialize forms and open main window. Fonts are initialized in
  398.      * display_text.
  399.      */
  400.  
  401.     bit_init();
  402.  
  403.     /*
  404.      * note that the load_optfile MUST appear after bit_init because of
  405.      * graphics. Also, need to save the variables (can't do the reverse
  406.      * either, i.e., store only s_ stuff in parsing, because some of the
  407.      * entries in opt panel depends on corresponding variables(bad globals)
  408.      */
  409.  
  410.     s_always_clear = always_clear;
  411.     s_verbose = verbose;
  412.     s_report = report_level;
  413.     s_g_zoomx = g_zoomx;
  414.     s_g_zoomy = g_zoomy;
  415.     s_showedit = showedit;
  416.     s_pause_index = slide_pause_index;
  417.     s_style = display_style;
  418.  
  419.     if (!noconfig)
  420.     (void) load_optfile(configfile, 1);
  421.  
  422.     /* overwrite the option with command line options */
  423.  
  424.     always_clear = s_always_clear;
  425.     slide_pause_index = s_pause_index;
  426.     verbose = s_verbose;
  427.     g_zoomx = s_g_zoomx;
  428.     g_zoomy = s_g_zoomy;
  429.     showedit = s_showedit;
  430.     report_level = s_report;
  431.     display_style = s_style;
  432.  
  433.     /* hints for best image quality */
  434.  
  435.     hardware_constraints(0);
  436.  
  437.     if (optind < argc && (make_list(argc - optind, argv + optind) == 0))
  438.     firstfile = next_file();
  439.  
  440.     /*
  441.      * if fit_image_size is active and there is no image file specified, need
  442.      * to open the main window otherwise there is no way to do that later
  443.      */
  444.  
  445.     if (fit_image_size && firstfile == 0)
  446.       {
  447.       fit_image_size = 0;
  448.       open_main_window(0);
  449.       }
  450.  
  451.  
  452.     return firstfile;
  453. }
  454.  
  455.  
  456. /********************************************************************
  457.  * Main keyboard handlers: Return -1 for finish keyin, 1 for
  458.  * finish all
  459.  *******************************************************************/
  460.  
  461. static int
  462. main_keybd(int key)
  463. {
  464.     int ret = 0;
  465.  
  466.     switch (key)
  467.       {
  468.       case 27:            /* ESC */
  469.       ret = 1;
  470.       break;
  471.       }
  472.     return ret;
  473. }
  474.  
  475. /*********************************************************************
  476.  * Main loop in main program. After loading and displaying, this routine
  477.  * waits for and handles events.
  478.  **********************************************************************/
  479.  
  480. static int
  481. process_Q(void)
  482. {
  483.     int done_keyin = 0, ret = 0;
  484.     long dev;
  485.     static short val;
  486.     static const char *func = "Process_Q";
  487.  
  488. #ifdef MTRACE
  489.     M_trace(func, "Enter");
  490. #endif
  491.  
  492.     while (!done_keyin)
  493.       {
  494.       dev = myqread(&val, LEFTMOUSE, slideshow);
  495.       switch ((dev = handle_const_q(dev, val)))
  496.         {
  497.         case KEYBD:
  498.         done_keyin = val && main_keybd(val);
  499.         ret = (done_keyin > 0);
  500.         break;
  501.  
  502.         case RIGHTMOUSE:
  503.         case PKEY:
  504.         done_keyin = val && ((fname = prev_file()) != 0);
  505.         break;
  506.  
  507.         case SPACEKEY:
  508.         case LEFTMOUSE:
  509.         done_keyin = (val > 0 && (fname = next_file()) != 0);
  510.         break;
  511.  
  512.         case MIDDLEMOUSE:
  513.         case CKEY:
  514.         done_keyin = val > 0;
  515.         break;
  516.  
  517.         default:
  518.         if (dev)
  519.             M_info(func, "Unknown event dev=%ld val=%d", dev, val);
  520.         break;
  521.         }
  522.       }
  523. #ifdef MTRACE
  524.     M_trace(func, "Exit");
  525. #endif
  526.     return ret;
  527. }
  528.  
  529.  
  530. static void
  531. remove_from_list(const char *s)
  532. {
  533.     if (auto_remove == 2 ||
  534.     (auto_remove == 1 && yes_no(s, "Remove from list ?", "", 0)))
  535.     delete_from_list1(s);
  536.  
  537. }
  538.  
  539. /**********************************************************************
  540.  * If fit_image is on and first image is bad. If there is still image
  541.  * left, open main window and go ahead. Otherwise, quit
  542.  **********************************************************************/
  543. static void
  544. special_case(void)
  545. {
  546.     if (fit_image_size && win_id < 0)
  547.       {
  548.       if (is_empty_list())
  549.           clean_up();
  550.       else
  551.         {
  552.         fit_image_size = 0;
  553.         open_main_window(imgptr);
  554.         }
  555.       }
  556. }
  557.  
  558. /*******************************************************************
  559.  * For all standard bit files, that is, files from BITDIR, HELPDIR etc
  560.  * we buffer all name complete requests.
  561.  ********************************************************************/
  562.  
  563. #define  NBITFILE  5        /* max. completed filename buffer */
  564.  
  565. static char bitfile[NBITFILE][MAXDLEN + MAXFLEN];
  566. static int cur_bf;
  567.  
  568. static FILE *
  569. bitopen(const char *dir, const char *f, const char *m)
  570. {
  571.     FILE *fp;
  572.  
  573.     strcat(strcpy(bitfile[cur_bf], dir), f);
  574.  
  575.     if (!(fp = fopen(bitfile[cur_bf], m)))
  576.     M_info("BITOPEN", "%s bad open", bitfile[cur_bf]);
  577.  
  578.     cur_bf++;
  579.     cur_bf %= NBITFILE;
  580.  
  581.     return fp;
  582. }
  583.  
  584. #ifndef BITDIR
  585. #define BITDIR "~/.bitrc"
  586. #endif
  587.  
  588. /******************************************************************
  589.  * for any given file, search current dir first, then env variable,
  590.  * and  default, and $home/.bitrc
  591.  *****************************************************************/
  592. #include <sys/stat.h>
  593.  
  594. FILE *
  595. get_BITfile_fp(const char *name, const char *m)
  596. {
  597.     FILE *fp;
  598.     const char *p;
  599.  
  600.     if (bitpath[0] == 0)
  601.       {                /* first time */
  602.       p = getenv("BITDIR");
  603.       fix_dir_tail(fix_dirname(strcpy(bitpath, p ? p : BITDIR)));
  604.       M_info("", "BITDIR=%s", bitpath);
  605.       }
  606.  
  607.     if (access(bitpath, F_OK | X_OK))
  608.       {
  609.       if (mkdir(bitpath, 0777))
  610.           M_warn("BITPATH", "Can't create %s", bitpath);
  611.       else
  612.         {
  613.         errno = 0;
  614.         M_info("BITPATH", "Created %s", bitpath);
  615.         }
  616.       }
  617.  
  618.     if (homedir[0] == 0)
  619.       {
  620.       if ((p = getenv("HOME")))
  621.           strcpy(homedir, p);
  622.       fix_dir_tail(fix_dirname(homedir));
  623.       M_info("", "HOME=%s", homedir);
  624.       strcat(homedir, ".bitrc/");
  625.       }
  626.  
  627.     /* try bitpath first */
  628.     if ((fp = bitopen(bitpath, name, m)))
  629.       {
  630.       M_info("getBitFile", "%s found in %s", name, bitpath);
  631.       return fp;
  632.       }
  633.  
  634.     /* try start up directory */
  635.     if ((fp = bitopen(startdir, name, m)))
  636.       {
  637.       M_info("getBitFile", "%s found in %s", name, startdir);
  638.       return fp;
  639.       }
  640.  
  641.     /* try current dir */
  642.     if ((fp = fopen(name, m)))
  643.     return fp;
  644.  
  645.     /* now try home if still not found */
  646.     if (!fp && strcmp(homedir, bitpath))
  647.     fp = bitopen(homedir, name, m);
  648.  
  649.     /* reset error 'cause previous failure is ok */
  650.     if (fp)
  651.     errno = 0;
  652.  
  653.     return fp;
  654. }
  655.  
  656. #ifndef BITHELP
  657. #define BITHELP "/usr/local/lib/bit"
  658. #endif
  659.  
  660. /********************************************************************
  661.  *  Given a (help) filename, return the complet path
  662.  *********************************************************************/
  663.  
  664. const char *
  665. get_HELPFile(const char *fn)
  666. {
  667.     static char hfile[512];
  668.     const char *p;
  669.  
  670.     if (helppath[0] == 0)
  671.       {                /* first time */
  672.       p = getenv("BITHELP");
  673.       fix_dir_tail(fix_dirname(strcpy(helppath, p ? p : BITHELP)));
  674.       M_info("", "BITHELP=%s", helppath);
  675.       }
  676.     return strcat(strcpy(hfile, helppath), fn);
  677. }
  678.  
  679. FILE *
  680. get_HELPfile_fp(const char *name, const char *m)
  681. {
  682.     FILE *fp;
  683.     const char *p;
  684.  
  685.     if (helppath[0] == 0)
  686.       {                /* first time */
  687.       p = getenv("BITHELP");
  688.       fix_dir_tail(fix_dirname(strcpy(helppath, p ? p : BITHELP)));
  689.       M_info("", "BITHELP=%s", helppath);
  690.       }
  691.     fp = bitopen(helppath, name, m);
  692.     return fp;
  693. }
  694.  
  695. #ifndef TMPDIR
  696. #define TMPDIR "/usr/tmp"
  697. #endif
  698.  
  699. const char *
  700. get_TMPfile(const char *name)
  701. {
  702.     static char nottmp[MAXDLEN];
  703.     char *ret;
  704.  
  705.     if (name[0] == '/' || name[0] == '~')
  706.       {
  707.       strcpy(nottmp, name);
  708.       return fix_dirname(nottmp);
  709.       }
  710.  
  711.     if (tmppath[0] == 0)
  712.       {
  713.       const char *p = getenv("TMPDIR");    /* cpp better be smart */
  714.       fix_dir_tail(strcpy(tmppath, p ? p : TMPDIR));
  715.       }
  716.  
  717.     ret = strcat(strcpy(bitfile[cur_bf], tmppath), name);
  718.  
  719.     /* advance bitfile buffer */
  720.     cur_bf++;
  721.     cur_bf %= NBITFILE;
  722.  
  723.     return ret;
  724. }
  725.  
  726. FILE *
  727. get_TMPfile_fp(const char *name, const char *mode)
  728. {
  729.     FILE *fp;
  730.     const char *q;
  731.  
  732.     if ((fp = fopen((q = get_TMPfile(name)), mode)))
  733.     return fp;
  734.  
  735.     M_err("GetTmpFp", "%s bad open", q);
  736.  
  737.     return 0;
  738. }
  739.  
  740. /***** remove all RCS keyword from Id ****/
  741. char *
  742. rm_rcs_kw(register const char *s)
  743. {
  744.     static char buf[255];
  745.     register char *q = buf;
  746.     int left = 0, lastc = -1;
  747.  
  748.     while (*s && (q - buf) < sizeof(buf) - 2)
  749.       {
  750.       switch (*s)
  751.         {
  752.         case '$':
  753.         left = !left;
  754.         if (left)
  755.           {
  756.               while (*s && *s != ':')
  757.               s++;
  758.           }
  759.         break;
  760.         default:
  761.         /* copy the char and remove extra space */
  762.         if (!(lastc == ' ' && *s == ' '))
  763.             *q++ = lastc = *s;
  764.         break;
  765.         }
  766.       s++;
  767.       }
  768.     *q = '\0';
  769.     return buf;
  770. }
  771.